/* 
 * File:   Matrix.h
 * Author: lusitanio
 *
 * Created on 2 de Abril de 2012, 15:16
 */

#ifndef MATRIX_H
#define	MATRIX_H
#include <iostream>
#include <vector>


using namespace std;

class Matrix {
private:
    int dx, dy; // dimensions, dx ´ dy
    float **p; // pointer to a pointer to a long integer
    int pa;
    void allocArrays() {
        p = new float*[dx];
        for (int i = 0; i < dx; i++) {
            p[i] = new float[dy];
        }
    }

public:

    Matrix(int sizeX = 1, int sizeY = 1, int pta = 0) : dx(sizeX), dy(sizeY),pa(pta) {
        allocArrays();
        reset();
    }

    ~Matrix() {
        for (int i = 0; i < dx; i++) {
            delete [] p[i];
        }
        delete [] p;
    }

    Matrix(const Matrix& m) {
        this->~Matrix();
        dx = m.dx;
        dy = m.dy;
        pa = m.pa;
        allocArrays();
        for (int i = 0; i < dx; ++i) {
            for (int j = 0; j < dy; ++j) {
                p[i][j] = m.p[i][j];
            }
        }
    }

    Matrix & operator =(const Matrix &m) {
        if (this == &m) {
            // avoid self-assignment
            return *this;
        } else {
            if (dx != m.dx || dy != m.dy) {
                this->~Matrix();
                dx = m.dx;
                dy = m.dy;
                pa = m.pa;
                allocArrays();
            }
            for (int i = 0; i < dx; i++) {
                for (int j = 0; j < dy; j++) {
                    p[i][j] = m.p[i][j];
                }
            }
            return *this;
        }
    }

    Matrix & operator+=(const Matrix & m) {
        // x+=y adds the y-entries into the x-entries
        for (int i = 0; i < dx; ++i) {
            for (int j = 0; j < dy; ++j) {
                p[i][j] += m.p[i][j];
            }
        }
        return *this;
    }

    Matrix operator+(const Matrix& m) {
        Matrix temp(*this); //copy constructor
        return (temp += m);
    }

    float & operator()(int i, int j) {
        return p[i][j];
    }

    
    void setPa(int pa) {
        this->pa = pa;
    }

    
    pair<int, float> min_cost_solo(int valor) {
        float menor_custo = 99999;
        int owner;
        for (int i = 0; i < dx; i++) {
            if ((menor_custo > p[i][valor])&&(pa!=i)) {
                menor_custo = p[i][valor];
                owner = i;
            }
        }
        return make_pair(owner, menor_custo);
    }

    pair<int, float> min_cost_pair(int valor0, int valor1) {
        float menor_custo = 99999;
        int owner;
        for (int i = 0; i < dx; i++) {
            if ((menor_custo > (p[i][valor0] + p[i][valor1]))&&(pa!=i)) {
                menor_custo = p[i][valor0] + p[i][valor1];
                owner = i;
            }
        }
        printf("OWNER: %d\n", owner);
        return make_pair(owner, menor_custo);
    }

    float prob_query_pair(int a, int b) {
        return p[a][b] / (sumRow(a) + sumRow(b) - p[a][b]);
    }

    float sumSelected(int o1, int o2, int pos1, int pos2) {
        return (p[o1][pos1] + p[o2][pos2]);
    }

    float sumRow(int row) {
        float w_return = 0.0;
        for (int j = 0; j < dy; j++) {
            w_return += p[row][j];
        }
        return w_return;
    }

    float sumColumn(int col) {
        float w_return = 0.0;
        for (int i = 0; i < dx; i++) {
            w_return += p[i][col];
        }
        return w_return;
    }    
    
    vector<float> vecSumRow(){
        vector<float> w_return(dx,0);
        for (int i = 0; i < dx; i++) {
            w_return[i] = sumRow(i);
        }
        return w_return;        
    } 
    
    vector<float> vecSumCol(){
        vector<float> w_return(dy,0);
        for (int j = 0; j < dy; j++) {
            w_return[j] = sumRow(j);
        }
        return w_return;         
    }     



    int getNcolumns() {
        return dy;
    }

    int getNrows() {
        return dx;
    }

    void print() {
        printf("**** MATRIX(%d,%d) ****\n", dx, dy);
        for (int i = 0; i < dx; ++i) {
            printf("Line[%2d]: ", i);
            for (int j = 0; j < dy; ++j) {
                printf(" %6.3f ", p[i][j]);
            }
            printf(" SUM = %6.3f \n", sumRow(i));
        }
        printf("  SUMS    ");
        for (int j = 0; j < dy; ++j) {
            printf(" %6.3f ", sumColumn(j));
        }
        puts(" ");
        printf("********\n");
    }

    void reset() {
        for (int i = 0; i < dx; i++) {
            for (int j = 0; j < dy; j++) {
                p[i][j] = 0.0;
            }
        }
    }



};


#endif	/* MATRIX_H */

